Strict
#Rem
Header: AGFX Framework - TBrush
#End
Import mojo
Import agfx

Const BRUSH_TYPE_LINE:Int		=1
Const BRUSH_TYPE_POLYLINE:Int	=2

Const BRUSH_STYLE_ROUNDED:Int 	=1
Const BRUSH_STYLE_HARD:Int 		=2
Const BRUSH_STYLE_SHARP:Int 	=3

Const BRUSH_STATE_DOWN:Int 		=0
Const BRUSH_STATE_DRAG:Int 		=1
Const BRUSH_STATE_UP:Int 		=2

#Rem
summary: TBrushTouchInput
#End
Class TBrushTouchInput Extends TTouchInput

	Field brush:TBrush

	Method New(b:TBrush)
		Self.brush = b
	End Method
	#rem
	summary: OnTouchHit
	' fired when you first touch the screen
	#End
	
	Method OnTouchHit:Void(x:Int, y:Int, pointer:Int)
	
		Self.brush.hit_pos[pointer].Set(x,y)
		Self.brush.state[pointer] = BRUSH_STATE_DOWN
		
	End
	
	#rem
	summary: OnTouchReleased
	fired when you release a finger from the screen
	#End
	
	Method OnTouchReleased:Void(x:Int, y:Int, pointer:Int)
		Self.brush.up_pos[pointer].Set(x,y)
		Self.brush.state[pointer] = BRUSH_STATE_UP
		self.brush.OnRelease.Call()
	End
	
	#rem
	summary: OnTouchDragged
	' fired when one of your fingers drags along the screen
	#End
	
	Method OnTouchDragged:Void(x:Int, y:Int, dx:Int, dy:Int, pointer:Int)
		Self.brush.drag_pos[pointer].Set(x,y)
		Self.brush.state[pointer] = BRUSH_STATE_DRAG
	End
	
	#rem
	summary: standard Click
	#End
	Method OnTouchClick:Void(x:Int, y:Int, pointer:Int)
	End
  
	#rem
	summary: OnTouchLongPress
	fired if you touch the screen and hold the finger in the same position for one second (configurable using game.inputCache.LongPressTime)
	this is checked at a specific time after touching the screen, so if you move your finger around and then
	hold it still, it won't fire
	#End
	
	Method OnTouchLongPress:Void(x:Int, y:Int, pointer:Int)
	End

	#rem
	summary: OnTouchFling
	 fired after you release a finger from the screen, if it was moving fast enough (configurable using game.inputCache.FlingThreshold)
	 velocityx/y/speed is in pixels per second, but speed is taken from the entire vector, by pythagoras
	 ie. velocitySpeed = Sqrt(velocityX*velocityX + velocityY*velocityY) in pixels per second
	#End
	
	Method OnTouchFling:Void(releaseX:Int, releaseY:Int, velocityX:Float, velocityY:Float, velocitySpeed:Float, pointer:Int)
	End	
	
End Class


#Rem
summary: TBrush
#End
Class TBrush
	
	Private
	
	Field hit_pos:TVector2[32]
	Field drag_pos:TVector2[32]
	Field up_pos:TVector2[32]
	Field state:Int[32]
	Field enable:Bool 
	Field rectangle:TPolygon
	Field size_start:Int	= 8
	Field size_end:Int		= 8
	Field Touch:TTouchControl
	
	Public
	#Rem
	summary: define color
	#End
	Field color:TColor
	#Rem
	summary: set type of brush
	Const BRUSH_TYPE_LINE:Int		=1
	Const BRUSH_TYPE_POLYLINE:Int	=2	<-- Not yet implemented
	#End
	Field type:Int
	#Rem
	summary: Style of brush shape
	Const BRUSH_STYLE_ROUNDED:Int 	=1
	Const BRUSH_STYLE_HARD:Int 		=2
	Const BRUSH_STYLE_SHARP:Int 	=3
	
	#End
	Field style:Int
	
	#Rem
	summary: 
	#End
	Field OnRelease:TCallback = New TCallback()
	
	#Rem
	summary:  Constructor
	#End
	Method New()
		Self.color 				= New TColor()		
		Self.type 				= BRUSH_TYPE_LINE
		Self.style 				= BRUSH_STYLE_ROUNDED
		Self.Touch 				= New TTouchControl()	
		Self.Touch.input 		= New TBrushTouchInput(Self)
		Self.enable				= False		
		Self.Touch.control.MonitorTouch(True)
		Self.color.WHITE()
		Self.rectangle = New TPolygon()

		Self.rectangle.AddPoint(New TVector2(-1,-1))
		Self.rectangle.AddPoint(New TVector2(-1,-1))
		Self.rectangle.AddPoint(New TVector2(-1,-1))
		Self.rectangle.AddPoint(New TVector2(-1,-1))
		Self.rectangle.AddPoint(New TVector2(-1,-1))
		Self.rectangle.AddPoint(New TVector2(-1,-1))

		For Local i:Int = 0 To 31
			Self.hit_pos[i] 	= New TVector2()
			Self.drag_pos[i] 	= New TVector2()	
			Self.up_pos[i] 		= New TVector2()	
			Self.state[i] 		= BRUSH_STATE_UP

		Next
		
	End Method
	#Rem
	summary: Enable draw brush 
	#End
	Method Enable:Void()
		Self.enable = True
	End Method
	#Rem
	summary: disable draw brush
	#End
	Method Disable:Void()
		Self.enable = False
	End Method
	#Rem
	summary: Update
	Add thso to your OnUpdate APP callback
	#End
	Method Update:Void()
		Self.Touch.Update()

	End Method
	#Rem
	summary: Set size
	A:Int value is used for set size start point and end point at same value
	#End
	Method SetSize:Void(A:Int)
		Self.size_start = A
		Self.size_end = A
	End
	#Rem
	summary: set size for:
	A:Int - start size
	B:Int - end size
	#End
	Method SetSize:Void(A:Int,B:Int)
		Self.size_start = A
		Self.size_end = B
	End
	
	#Rem
	summary: Render
	Add thso to your OnRender APP callback
	#End
	Method Render:Void()
	
		If Self.enable Then
			Self.color.Apply()
			
			For Local i:Int=0 To 31
				If Self.state[i] = BRUSH_STATE_DRAG Then 
					Self.DrawBrushLine(i)
				EndIf
				
			Next
			
		End If
		
	End Method
	
	Private
	
	Method DrawBrushLine:Void(i:Int)

		Local dir:TVector2 		= VecSub(Self.drag_pos[i],Self.hit_pos[i])
		Local len:FLoat    		= VecLength(dir)		
		dir = VecNormalize(dir)
		Local l_norm_s:TVector2	= VecLeftNormal(dir)		
		Local r_norm_s:TVector2	= VecRightNormal(dir)
		Local l_norm_e:TVector2	= VecLeftNormal(dir)		
		Local r_norm_e:TVector2	= VecRightNormal(dir)

		Local A:TVector2
		Local B:TVector2
		Local C:TVector2		
		Local D:TVector2
		Local E:TVector2
		Local F:TVector2

		

		If Self.style = BRUSH_STYLE_ROUNDED Or Self.style = BRUSH_STYLE_HARD Then


			l_norm_s.Mult(Self.size_start)
			r_norm_s.Mult(Self.size_start)

			l_norm_e.Mult(Self.size_end)
			r_norm_e.Mult(Self.size_end)

			A = New TVector2(Self.hit_pos[i])
			B = New TVector2(VecAdd(A,l_norm_s))
			F = New TVector2(VecAdd(A,r_norm_s))
			
			C = New TVector2(VecAdd(Self.drag_pos[i],l_norm_e))
			D = New TVector2(Self.drag_pos[i])
			E = New TVector2(VecAdd(Self.drag_pos[i],r_norm_e))
		Else
			
			l_norm_s.Mult(Self.size_start)
			r_norm_s.Mult(Self.size_start)

			l_norm_e.Mult(Self.size_end)
			r_norm_e.Mult(Self.size_end)

			A  = New TVector2(Self.hit_pos[i])

			Local MID:TVector2 = New TVector2(A)
			MID = VecAdd(MID,VecMult(dir,len*0.8))

			B = New TVector2(VecAdd(MID,l_norm_s))
			F = New TVector2(VecAdd(MID,r_norm_s))
			
			C = New TVector2(VecAdd(MID,l_norm_e))
			D = New TVector2(Self.drag_pos[i])
			E = New TVector2(VecAdd(MID,r_norm_e))

		EndIf

		' /B-------------------------C\
		' A                           D
		' \F-------------------------E/

		If Self.style = BRUSH_STYLE_ROUNDED Then
			DrawCircle(Self.hit_pos[i].x,Self.hit_pos[i].y,Self.size_start)
			DrawCircle(Self.drag_pos[i].x,Self.drag_pos[i].y,Self.size_end)
		End
		
		' [A]
		Self.rectangle.points.Get(0).Set(A)
		' [B]'
		Self.rectangle.points.Get(1).Set(B)
		' [C]'
		Self.rectangle.points.Get(2).Set(C)
		' [D]'
		Self.rectangle.points.Get(3).Set(D)
		' [E]'
		Self.rectangle.points.Get(4).Set(E)
		' [F]'
		Self.rectangle.points.Get(5).Set(F)

		Self.rectangle.Update()

		Self.rectangle.Draw()

		If DEBUG Then Self.rectangle.DrawDebug()
	End
End Class